package ink.xiaobaibai.filter;

import ink.xiaobaibai.handler.JWTSuccessHandler;
import ink.xiaobaibai.token.JWTAuthenticationToken;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @description: token校验过滤器
 * @author: 小白白
 * @create: 2021-05-14
 **/

public class TokenAuthenticationFilter extends OncePerRequestFilter {

    /**
     * 思考一下,这里的rbac接口,要不就全部匹配得了,因为后续的rbac接口直接去查数据库的uri和角色的,此处只是加身份的过滤器
     */
    private AuthenticationManager authenticationManager;
    private JWTSuccessHandler jwtSuccessHandler;

    public TokenAuthenticationFilter(AuthenticationManager authenticationManager) {
        this.authenticationManager = authenticationManager;
        this.jwtSuccessHandler = new JWTSuccessHandler();
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {

        String jwt = this.getToken(request);
        if (jwt != null) {
            //去验证此jwt是否正确
            JWTAuthenticationToken jwtAuthenticationToken = new JWTAuthenticationToken(jwt);
            Authentication authenticate = this.authenticationManager.authenticate(jwtAuthenticationToken);
            if (authenticate != null) {
                this.successfulAuthentication(request, response, filterChain, authenticate);
            }
            //返回的角色为空,说明jwt错了,也继续走下去,后续的rbac接口会处理
        }
        filterChain.doFilter(request, response);
    }

    /**
     * 验证成功后置处理
     *
     * @param request
     * @param response
     * @param chain
     * @param authResult
     * @throws IOException
     * @throws ServletException
     */
    protected void successfulAuthentication(HttpServletRequest request,
                                            HttpServletResponse response, FilterChain chain, Authentication authResult)
            throws IOException, ServletException {
        //更新身份(不会覆盖,已经在provider中特殊处理)
        SecurityContextHolder.getContext().setAuthentication(authResult);
        //去经过成功处理器,更新token
        this.jwtSuccessHandler.onAuthenticationSuccess(request, response, authResult);
    }

    private String getToken(HttpServletRequest request) {
        return request.getHeader("Authorization");
    }

}
